﻿#region License
/* Copyright (C) 2009 Tim Coulter
 * 
 * This file is part of ExtremeML.
 * 
 * ExtremeML is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation either version
 * 2 of the License, or (at your option) any later version.
 * 
 * ExtremeML is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
*/
#endregion

using System;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Xml.Linq;

namespace ExtremeML.Samples
{
	public static class Utility
	{
		private const string ExcelSampleDataResource = @"ExtremeML.Samples.Resources.Sample Data.xlsx";
		private const string XmlSampleDataResource = @"ExtremeML.Samples.Resources.Sample Data.xml";
		private const string XmlSampleDataPhysicalPath = @"..\..\Resources\Sample Data.xml";
		private const string SampleImagesResourceTemplate = @"ExtremeML.Samples.Resources.Images.{0}";

		public const string TemplateWorkbookResource = @"ExtremeML.Samples.Resources.Template Workbook.xlsx";
		public const string EmptyWorkbookResource = @"ExtremeML.Samples.Resources.Empty Workbook.xlsx";
		public const string TargetOutputFile = @"..\..\Target.xlsx";

		private static readonly Random Random = new Random();
		private static readonly string[] Strings = new[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };

		private static readonly Uri[] Uris = new[] 
			{
				new Uri("http://www.microsoft.com/"),
				new Uri("http://www.google.com/"),
				new Uri("http://www.yahoo.com"),
				new Uri("http://www.youtube.com"),
				new Uri("http://www.bbc.co.uk/")
			};

		private static readonly string[] Images = new[]
          	{
                "sample1.jpg",
                "sample2.png",
                "sample3.jpg"
          	};

		/// <summary>
		/// Returns a random string value.
		/// </summary>
		public static Bitmap GetRandomImage()
		{
			//var path = string.Format(SampleImagesResourceTemplate, Images[Random.Next(3)]);
			var path = string.Format(SampleImagesResourceTemplate, Images[1]);
			var data = new byte[4096];
			var outStream = new MemoryStream();

			using (var inStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path))
			{
				int bytes;

				do
				{
					bytes = inStream.Read(data, 0, 4096);
					outStream.Write(data, 0, bytes);
				} while (bytes > 0);
			}

			return new Bitmap(outStream);
		}

		/// <summary>
		/// Returns a random string value.
		/// </summary>
		public static string GetRandomString()
		{
			return Strings[Random.Next(10)];
		}

		/// <summary>
		/// Returns a random Uri value.
		/// </summary>
		public static Uri GetRandomUri()
		{
			return Uris[Random.Next(5)];
		}

		/// <summary>
		/// Returns a random DateTime value.
		/// </summary>
		public static DateTime GetRandomDateTime()
		{
			return DateTime.Now.AddDays(Random.Next(1000));
		}

		/// <summary>
		/// Returns a random TimeSpan value.
		/// </summary>
		public static TimeSpan GetRandomTimeSpan()
		{
			return new TimeSpan(0, 0, 0, Random.Next(86400));
		}

		/// <summary>
		/// Returns a random Integer value.
		/// </summary>
		public static int GetRandomInteger()
		{
			return Random.Next(10000);
		}

		/// <summary>
		/// Returns a random Double value.
		/// </summary>
		public static double GetRandomDouble()
		{
			return Random.Next(10000) / 27.53d;
		}

		/// <summary>
		/// Returns a random Decimal value.
		/// </summary>
		public static decimal GetRandomDecimal()
		{
			return Random.Next(10000) / 13.6m;
		}

		/// <summary>
		/// Returns a random Boolean value.
		/// </summary>
		public static bool GetRandomBoolean()
		{
			return Random.Next(100)%2 == 0;
		}

        /// <summary>
        /// Returns a string that demonstrates a range of rich-text markup.
        /// </summary>
        public static string GetSampleRichText()
        {
            return "This sentence has <b>bold <i>and</b> italic</i> overlapping.\n\n"
                + "This has <u>underline</u> and <strike>strike-through</strike>.\n\n"
                + "This is <valign value=\"subscript\">subscript</valign> "
                + "and this is <valign value=\"superscript\">superscript</valign>.\n\n"
                + "This one adds a <font name=\"Courier\">font change "
                +"and <font color=\"#FF0000\">colored</font> text</font>.";
        }

		/// <summary>
		/// Populates and returns a DataSet containing the sample Xml data.
		/// </summary>
		public static DataSet GetSampleDataSet()
		{
			var dataSet = new DataSet();
			dataSet.ReadXml(CreateFileFromResource(XmlSampleDataResource));
			return dataSet;
		}

		/// <summary>
		/// Populates and returns an XDocument containing the sample Xml data.
		/// </summary>
		public static XDocument GetSampleDataXml()
		{
			return XDocument.Load(CreateFileFromResource(XmlSampleDataResource));
		}

		/// <summary>
		/// Builds a DataSet from the sample data Excel workbook and saves it to Xml.
		/// </summary>
		public static void BuildSampleDataXml()
		{
			const string connectionStringTemplate = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0}; Extended Properties=""Excel 12.0;IMEX=1;HDR=YES""";

			using (var connection = new OleDbConnection())
			{
				connection.ConnectionString = string.Format(connectionStringTemplate, CreateFileFromResource(ExcelSampleDataResource));
				connection.Open();

				var dataSet = new DataSet();
				var adapter = new OleDbDataAdapter("SELECT * FROM [Countries$]", connection);
				var table = new DataTable("Countries");

				adapter.Fill(table);
				connection.Close();

				table.Columns["Country"].Caption = "Country";
				table.Columns["Capital"].Caption = "Capital City";
				table.Columns["Language"].Caption = "Main Language";
				table.Columns["CurrencyCode"].Caption = "Currency";
				table.Columns["ExchangeRate"].Caption = "US$ Rate";
				table.Columns["Population"].Caption = "Population";
				table.Columns["GDP"].Caption = "GDP ($M)";

				dataSet.Tables.Add(table);
				dataSet.WriteXml(XmlSampleDataPhysicalPath, XmlWriteMode.WriteSchema);
			}
		}

		/// <summary>
		/// Copies the specified resource to a temporary file and returns its path.
		/// </summary>
		public static string CreateFileFromResource(
			string resourcePath)
		{
			var filePath = Path.GetTempFileName();
			CreateFileFromResource(resourcePath, filePath);
			return filePath;
		}

		/// <summary>
		/// Copies the specified resource to the specified path.
		/// </summary>
		public static void CreateFileFromResource(
			string resourcePath,
			string filePath)
		{
			var data = new byte[4096];

			using (var inStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath))
			using (var outStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
			{
				int bytes;

				do
				{
					bytes = inStream.Read(data, 0, 4096);
					outStream.Write(data, 0, bytes);
				} while (bytes > 0);
			}
		}

		/// <summary>
		/// Returns a temporary file path to for use in creating a new package.
		/// </summary>
		public static string GetTemporaryFilePath()
		{
			return Path.GetTempFileName();
		}
	}
}
